# twitter_bot/post_tweet.py (增强版，支持多图并演示限制)
import tweepy
import yaml
import time
import os
from typing import List

def load_config():
    """加载配置文件"""
    try:
        with open('config.yaml', 'r', encoding='utf-8') as f:
            return yaml.safe_load(f)
    except Exception as e:
        print(f"❌ 加载配置失败: {e}")
        return None

def get_api_v1(config):
    """获取 v1.1 API 客户端，用于媒体上传"""
    auth = tweepy.OAuth1UserHandler(
        config['api_key'], config['api_key_secret'],
        config['access_token'], config['access_token_secret']
    )
    return tweepy.API(auth)

def get_client_v2(config):
    """获取 v2 API 客户端，用于发推"""
    return tweepy.Client(
        consumer_key=config['api_key'],
        consumer_secret=config['api_key_secret'],
        access_token=config['access_token'],
        access_token_secret=config['access_token_secret']
    )

def post_media_tweet(config, text: str, image_paths: List[str] = None, video_path: str = None):
    """
    发布带媒体的推文。
    注意：Twitter API 不允许在同一条推文中混合图片和视频。
    """
    if not text and not image_paths and not video_path:
        print("❌ 错误：必须提供文本、图片或视频之一。")
        return
    
    if image_paths and video_path:
        print("❌ API 限制: 不能在同一条推文中同时上传图片和视频。")
        return

    try:
        api_v1 = get_api_v1(config)
        client_v2 = get_client_v2(config)
        
        media_ids = []
        # --- 上传图片 ---
        if image_paths:
            for image_path in image_paths:
                if not os.path.exists(image_path):
                    print(f"❌ 图片文件未找到: {image_path}")
                    continue
                print(f"正在上传图片: {image_path}...")
                media = api_v1.media_upload(filename=image_path)
                media_ids.append(media.media_id_string)
            print("✅ 所有图片上传成功!")

        # --- 上传视频 ---
        if video_path:
            if not os.path.exists(video_path):
                print(f"❌ 视频文件未找到: {video_path}")
                return
            print(f"正在上传视频: {video_path}...")
            media = api_v1.media_upload(filename=video_path, media_category='tweet_video', chunked=True)
            print("⏳ 视频上传处理中，请稍候...")
            # 轮询上传状态
            while media.processing_info['state'] in ['pending', 'in_progress']:
                check_after_secs = media.processing_info.get('check_after_secs', 5)
                time.sleep(check_after_secs)
                media = api_v1.get_media_upload_status(media_id=media.media_id_string)
            
            if media.processing_info['state'] == 'succeeded':
                media_ids.append(media.media_id_string)
                print("✅ 视频上传成功!")
            else:
                error_info = media.processing_info.get('error', {})
                print(f"❌ 视频上传失败: {error_info.get('message', '未知错误')}")
                return

        print(f"准备发布推文: '{text}'")
        response = client_v2.create_tweet(text=text, media_ids=media_ids if media_ids else None)
        
        print("\n✅ 推文发布成功！")
        print(f"链接: https://twitter.com/user/status/{response.data['id']}")

    except tweepy.errors.TweepyException as e:
        print(f"\n❌ 发布推文时出错: {e}")
    except KeyError as e:
        print(f"❌ 配置错误: 你的 config.yaml 文件缺少必要的密钥/令牌: {e}")
    except Exception as e:
        print(f"❌ 发生未知错误: {e}")

def main():
    """主测试函数"""
    config = load_config()
    if not config:
        return

    # 准备测试文件
    image_file_1 = "pic.jpg"
    video_file = "1.mp4" # 按要求修改文件名
    if not os.path.exists(image_file_1): print(f"警告: 未找到 {image_file_1}，部分测试将跳过。")
    if not os.path.exists(video_file): print(f"警告: 未找到 {video_file}，部分测试将跳过。")
        
    print("--- 1. 测试发布纯文本推文 ---")
    #post_media_tweet(config, text="[Test 1] 这是一个纯文本测试推文。 #Python #TwitterBot")
    #time.sleep(5)


    print("\n--- 2. 测试发布单张图片推文 ---")
    #post_media_tweet(config, text="[Test 2] 这是一个带单张图片的测试推文！", image_paths=[image_file_1])
    #time.sleep(5)

    print("\n--- 3. 测试发布视频推文 ---")
    #post_media_tweet(config, text="[Test 3] 这是一个带视频的测试推文！", video_path=video_file)
    # 视频处理需要更长时间
    #time.sleep(15)





if __name__ == "__main__":
    main()